//
//  ServiceColorEditController.swift
//  home
//
//  Created by Yun Zeng on 2019/9/29.
//  Copyright © 2019 Yun Zeng. All rights reserved.
//

import UIKit

class ServiceColorEditController: UIViewController {
    @IBOutlet weak var navigationBar: UINavigationBar!
    
    var light: ServiceLightHue!

    private lazy var colorEditView: RGBColorView = {
        let view = RGBColorView(frame: .zero)
        return view
    } ()
    
    // 常用颜色选中框
    private lazy var favoriteRadios: FavoriteColorView = {
        let view = FavoriteColorView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 124))
        view.translatesAutoresizingMaskIntoConstraints = false
        
        view.heightAnchor.constraint(equalToConstant: 124).isActive = true
        view.widthAnchor.constraint(equalToConstant: 190).isActive = true
        view.backgroundColor = UIColor.clear
        return view
    } ()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        Logger.Info("ServiceColorEditController")
        
        self.view.backgroundColor = UIColor(hex: "dedede")
        
        self.view.addSubview(self.colorEditView)
        colorEditView.translatesAutoresizingMaskIntoConstraints = false
        colorEditView.heightAnchor.constraint(equalToConstant: 323).isActive = true
        colorEditView.widthAnchor.constraint(equalToConstant: 323).isActive = true
        colorEditView.topAnchor.constraint(equalTo: self.navigationBar.bottomAnchor, constant: 83).isActive = true
        colorEditView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        let gesture = UIPanGestureRecognizer(target: nil, action: nil)
        gesture.cancelsTouchesInView = false
        colorEditView.addGestureRecognizer(gesture)
        
        colorEditView.setColor(color: UIColor(hex: self.light.colorValue))
        colorEditView.posViewMoveTo(point: CGPoint(x: 162, y: 162), color: UIColor.white)
        
        favoriteRadios.setColor(color: self.light.colorValue)
        self.view.addSubview(self.favoriteRadios)
        favoriteRadios.topAnchor.constraint(equalTo: self.navigationBar.bottomAnchor, constant: 478).isActive = true
        favoriteRadios.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        
        favoriteRadios.onColor = { (color, _) in
            self.colorEditView.setColor(color: color)
            self.light.setColor(color: color.toHexString)
        }
        
        colorEditView.onColor = { color in
            self.light.setColor(color: color.toHexString)
            self.favoriteRadios.setColor(color: color.toHexString)
        }
    }

    @IBAction func save(_ sender: Any) {
        self.dismiss(animated: true)
    }
    
    @IBAction func cancel(_ sender: Any) {
        self.dismiss(animated: true)
    }
    
}


// MARK: -当前颜色指示图标
fileprivate class ColorPosView: UIView {
    override func draw(_ rect: CGRect) {
        self.drawPos()
    }
    
    enum ResizingBehavior {
        case aspectFit
        case aspectFill
        case stretch
        case center
        
        func apply(rect: CGRect, target: CGRect) -> CGRect {
            if rect == target || target == CGRect.zero {
                return rect
            }
            
            var scales = CGSize.zero
            scales.width = abs(target.width / rect.width)
            scales.height = abs(target.height / rect.height)
            
            switch self {
            case .aspectFit:
                scales.width = min(scales.width, scales.height)
                scales.height = scales.width
            case .aspectFill:
                scales.width = max(scales.width, scales.height)
                scales.height = scales.width
            case .stretch:
                break
            case .center:
                scales.width = 1
                scales.height = 1
            }
            
            var result = rect.standardized
            result.size.width *= scales.width
            result.size.height *= scales.height
            result.origin.x = target.minX + (target.width - result.width) / 2
            result.origin.y = target.minY + (target.height - result.height) / 2
            return result
        }
    }
    
    static var color: UIColor = UIColor.white
    
    private func drawPos(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 74, height: 84), resizing: ResizingBehavior = .aspectFit) {
        /// General Declarations
        let context = UIGraphicsGetCurrentContext()!
        let baseTransform = context.userSpaceToDeviceSpaceTransform.inverted()
        
        context.saveGState()
        let resizedFrame = resizing.apply(rect: CGRect(x: 0, y: 0, width: 74, height: 84), target: targetFrame)
        context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
        context.scaleBy(x: resizedFrame.width / 74, y: resizedFrame.height / 84)
        
        let oval6Copy = UIBezierPath()
        oval6Copy.move(to: CGPoint(x: 21.53, y: 50))
        oval6Copy.addCurve(to: CGPoint(x: 35.07, y: 37.5), controlPoint1: CGPoint(x: 28.36, y: 44.39), controlPoint2: CGPoint(x: 32.87, y: 40.23))
        oval6Copy.addCurve(to: CGPoint(x: 42, y: 20.59), controlPoint1: CGPoint(x: 39.83, y: 31.61), controlPoint2: CGPoint(x: 42, y: 24.98))
        oval6Copy.addCurve(to: CGPoint(x: 21.01, y: 0), controlPoint1: CGPoint(x: 42, y: 9.43), controlPoint2: CGPoint(x: 32.54, y: 0))
        oval6Copy.addCurve(to: CGPoint(x: 0, y: 20.59), controlPoint1: CGPoint(x: 9.47, y: 0), controlPoint2: CGPoint(x: 0, y: 9.43))
        oval6Copy.addCurve(to: CGPoint(x: 7.85, y: 38.14), controlPoint1: CGPoint(x: 0, y: 25.22), controlPoint2: CGPoint(x: 2.29, y: 31.68))
        oval6Copy.addCurve(to: CGPoint(x: 21.53, y: 50), controlPoint1: CGPoint(x: 10.1, y: 40.75), controlPoint2: CGPoint(x: 14.66, y: 44.71))
        oval6Copy.close()
        context.saveGState()
        context.translateBy(x: 16, y: 15)
        context.saveGState()
        context.beginPath()
        context.addPath(oval6Copy.cgPath)
        context.addRect(oval6Copy.bounds.insetBy(dx: -104, dy: -104))
        context.clip(using: .evenOdd)
        context.translateBy(x: -247, y: 0)
        do {
            let baseZero = context.convertToDeviceSpace(CGPoint.zero).applying(baseTransform)
            let baseOne = context.convertToDeviceSpace(CGPoint(x: 1, y: 1)).applying(baseTransform)
            let baseOffset = context.convertToDeviceSpace(CGPoint(x: 247, y: 0)).applying(baseTransform)
            let shadowOffset = CGSize(width: baseOffset.x - baseZero.x, height: baseOffset.y - baseZero.y)
            let shadowBlur: CGFloat = 4 * min(baseOne.x - baseZero.x, baseOne.y - baseZero.y)
            context.setShadow(offset: shadowOffset, blur: shadowBlur, color: UIColor(white: 0, alpha: 0.5).cgColor)
        }
        context.beginTransparencyLayer(auxiliaryInfo: nil)
        do {
            UIColor.black.setFill()
            oval6Copy.fill()
            context.saveGState()
            oval6Copy.lineWidth = 10
            context.beginPath()
            context.addPath(oval6Copy.cgPath)
            context.addRect(oval6Copy.bounds.insetBy(dx: -100, dy: -100))
            context.clip(using: .evenOdd)
            UIColor.black.setStroke()
            oval6Copy.stroke()
            context.restoreGState()
        }
        context.endTransparencyLayer()
        context.restoreGState()
        
        self.color.setFill()
        
        oval6Copy.fill()
        context.saveGState()
        oval6Copy.lineWidth = 10
        context.beginPath()
        context.addPath(oval6Copy.cgPath)
        context.addRect(oval6Copy.bounds.insetBy(dx: -100, dy: -100))
        context.clip(using: .evenOdd)
        UIColor.white.setStroke()
        oval6Copy.stroke()
        context.restoreGState()
        context.restoreGState()
        context.restoreGState()
    }
    
    var color: UIColor = UIColor.clear {
        didSet {
            self.setNeedsDisplay()
        }
    }
}

// MARK: - RGB圆盘上的颜色
extension UIImage {
    func getPixels() -> [UIColor] {
        guard let cgImage = self.cgImage else {
            return []
        }
        assert(cgImage.bitsPerPixel == 32, "only support 32 bit images")
        assert(cgImage.bitsPerComponent == 8,  "only support 8 bit per channel")
        guard let imageData = cgImage.dataProvider?.data as Data? else {
            return []
        }
        let size = cgImage.width * cgImage.height
        let buffer = UnsafeMutableBufferPointer<UInt32>.allocate(capacity: size)
        _ = imageData.copyBytes(to: buffer)
        var result = [UIColor]()
        result.reserveCapacity(size)
        for pixel in buffer {
            var r : UInt32 = 0
            var g : UInt32 = 0
            var b : UInt32 = 0
            if cgImage.byteOrderInfo == .orderDefault || cgImage.byteOrderInfo == .order32Big {
                r = pixel & 255
                g = (pixel >> 8) & 255
                b = (pixel >> 16) & 255
            } else if cgImage.byteOrderInfo == .order32Little {
                r = (pixel >> 16) & 255
                g = (pixel >> 8) & 255
                b = pixel & 255
            }
            let color = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1)
            result.append(color)
        }
        return result
    }
    
    // 按照圆的直径获取指定的像素颜色，比获取全部颜色在iphoneXS快9倍
    func getPixelsByPoints(diameter: Int) -> [UIColor] {
        guard let cgImage = self.cgImage else {
            return []
        }
        Logger.Info("bits: \(cgImage.bitsPerPixel) component: \(cgImage.bitsPerComponent)")
        assert(cgImage.bitsPerPixel == 32, "only support 32 bit images")
        assert(cgImage.bitsPerComponent == 8,  "only support 8 bit per channel")
        guard let imageData = cgImage.dataProvider?.data as Data? else {
            return []
        }
        let size = cgImage.width * cgImage.height
        let buffer = UnsafeMutableBufferPointer<UInt32>.allocate(capacity: size)
        _ = imageData.copyBytes(to: buffer)
        var result = [UIColor]()
        result.reserveCapacity(size)
        let scale = Int(self.cgImage!.width / diameter)
        let imgWidth = Int(self.cgImage!.width)
        for x in 0 ..< diameter {
            for y in 0 ..< diameter {
                let offset = y * scale * imgWidth + x * scale
                let pixel = buffer[offset]
                var r : UInt32 = 0
                var g : UInt32 = 0
                var b : UInt32 = 0
                if cgImage.byteOrderInfo == .orderDefault || cgImage.byteOrderInfo == .order32Big {
                    r = pixel & 255
                    g = (pixel >> 8) & 255
                    b = (pixel >> 16) & 255
                } else if cgImage.byteOrderInfo == .order32Little {
                    r = (pixel >> 16) & 255
                    g = (pixel >> 8) & 255
                    b = pixel & 255
                }
                let color = UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1)
                result.append(color)
            }
        }
        return result
    }
}

// MARK: RGB圆环
fileprivate class RGBColorView: UIView {
    // 圆环直径
    fileprivate let circleDiameter: Int = 323
    fileprivate let yOffset = 0
    fileprivate lazy var xOffset: Int = 0
    fileprivate var currentColor: UIColor?
    
    // 背景圆环位置
    private lazy var background: UIImageView = {
        let img = UIImageView(frame: .zero)
        img.image = UIImage(named: "panel-light-color-edit")
        return img
    }()
    
    // 选中颜色箭头位置
    private lazy var posView: ColorPosView = {
        let pos = ColorPosView(frame: CGRect(x: 0, y: 0, width: 74, height: 84))
        pos.backgroundColor = UIColor.clear
        pos.frame = CGRect(x: self.circleDiameter/2  - 74/2, y: self.circleDiameter/2 - 84 + yOffset, width: 74, height: 84)
        pos.color = UIColor.white
        pos.layer.shadowColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4).cgColor
        pos.layer.shadowOffset = CGSize.zero
        pos.layer.shadowRadius = 4.0
        pos.layer.shadowOpacity = 1.0
        return pos
    }()
    
    // 圆环区域颜色集
    private var circleColors = [UIColor]()
    // 设置颜色集
    func setCircleColors(img: UIImage) {
        DispatchQueue.global().async {
            self.circleColors = img.getPixelsByPoints(diameter: self.circleDiameter)
            if let color = self.currentColor {
                DispatchQueue.main.async {
                    self.setColor(color: color)
                }
            }
        }
    }
    
    // 获取颜色
    func getCircleColor(x: Int, y: Int) -> UIColor? {
        if self.circleColors.count < self.circleDiameter * self.circleDiameter  {
            return nil
        }
        if x < 0 || x >= self.circleDiameter || y < 0 || y >= self.circleDiameter {
            return nil
        }
        let color = self.circleColors[x * self.circleDiameter + y]
        let components = color.cgColor.components!
        if components[0] == 0.0 && components[1] == 0.0 && components[2] == 0.0 {
            return nil
        }
        return color
    }
    
    // 通过颜色获取位置
    func getCirclePos(color: UIColor) -> CGPoint {
        var point = CGPoint(x: 0, y: 0)
        var max: CGFloat = 3.0
        let components = color.cgColor.components!
        for x in 0 ..< self.circleDiameter {
            for y in 0 ..< self.circleDiameter {
                if let color = self.getCircleColor(x: x, y: y), let coms = color.cgColor.components {
                    let d = sqrt((coms[0] - components[0]) * (coms[0] - components[0]) + (coms[1] - components[1]) * (coms[1] - components[1]) + (coms[2] - components[2]) * (coms[2] - components[2]))
                    if d < max {
                        max = d
                        point = CGPoint(x: x, y: y)
                    }
                }
            }
        }
        return point
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(self.background)
        
        self.background.translatesAutoresizingMaskIntoConstraints = false
        self.background.widthAnchor.constraint(equalToConstant: CGFloat(circleDiameter)).isActive = true
        self.background.heightAnchor.constraint(equalToConstant: CGFloat(circleDiameter)).isActive = true
        self.background.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        self.background.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
        
        self.addSubview(self.posView)
        self.setCircleColors(img: self.background.image!)
        print("circle colors size: \(self.circleColors.count)")
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    var onColor: ((_ color: UIColor) -> Void)?
    
    func posViewMoveTo(point: CGPoint, color: UIColor = UIColor.white)  {
        self.posView.frame = CGRect(x: point.x - 74/2, y: point.y - 84 + 12, width: 74, height: 84)
        self.posView.color = color
    }
    
    enum movedState: Int {
        case began
        case moved
        case ended
    }
    
    // 显示颜色
    func displayColor(point: CGPoint, state: movedState = .moved) {
        let x = Int(point.x) - self.xOffset
        let y = Int(point.y) - self.yOffset
        if let color = self.getCircleColor(x: x, y: y) {
            if state != .moved {
                self.onColor?(color)
            }
            UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [], animations: {
                self.posViewMoveTo(point: point, color: color)
            }, completion: nil)
        } else {
            print("color: nil")
        }
    }
    
    func setColor(color: UIColor) {
        self.currentColor = color
        let point = self.getCirclePos(color: color)
        UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [], animations: {
            self.posViewMoveTo(point: point, color: color)
        }, completion: nil)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let point = touches.first!.preciseLocation(in: self)
        self.displayColor(point: point, state: .began)
        return super.touchesBegan(touches, with: event)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        let point = touches.first!.preciseLocation(in: self)
        self.displayColor(point: point, state: .ended)
        return super.touchesEnded(touches, with: event)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let point = touches.first!.preciseLocation(in: self)
        self.displayColor(point: point, state: .moved)
        return super.touchesMoved(touches, with: event)
    }
}



